package com.tlgen.modules.common.service.impl;

import com.tlgen.common.exception.EntityExistException;
import com.tlgen.common.utils.FileUtil;
import com.tlgen.common.utils.PageUtil;
import com.tlgen.common.utils.QueryHelp;
import com.tlgen.common.utils.ValidationUtil;
import com.tlgen.modules.common.domain.Rate;
import com.tlgen.modules.common.repository.RateRepository;
import com.tlgen.modules.common.service.RateService;
import com.tlgen.modules.common.service.dto.RateDto;
import com.tlgen.modules.common.service.dto.RateQueryCriteria;
import com.tlgen.modules.common.service.mapper.RateMapper;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;

@Service
@CacheConfig(cacheNames = "Rate")
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class RateServiceImpl implements RateService {

    private final RateRepository rateRepository;

    private final RateMapper rateMapper;

    public RateServiceImpl(RateRepository rateRepository, RateMapper rateMapper) {
        this.rateRepository = rateRepository;
        this.rateMapper = rateMapper;
    }


    /**
     * 不带条件分页查询
     * @param pageable 分页参数
     * @return
     */
    @Override
    @Cacheable
    public Object queryAll(Pageable pageable) {
        return rateMapper.toDto(rateRepository.findAll(pageable).getContent());
    }


    /**
     * 带条件分页查询
     * @param criteria 条件
     * @param pageable 分页参数
     * @return
     */
    @Override
    @Cacheable
    public Object queryAll(RateQueryCriteria criteria, Pageable pageable) {
        Page<Rate> page = rateRepository.findAll((root, criteriaQuery, criteriaBuilder) ->
                QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable);
        return PageUtil.toPage(page.map(rateMapper::toDto));
    }

    /**
     * 带条件不分页查询
     * @param criteria 条件
     * @return
     */
    @Override
    @Cacheable
    public List<RateDto> queryAll(RateQueryCriteria criteria) {
        return rateMapper.toDto(rateRepository.findAll((root, criteriaQuery, criteriaBuilder) ->
                QueryHelp.getPredicate(root,criteria,criteriaBuilder)));
    }

    /**
     * 新增
     * @param resources /
     * @return
     */
    @Override
    @CacheEvict(allEntries = true)
    @Transactional(rollbackFor = Exception.class)
    public RateDto create(Rate resources) {
        if(rateRepository.findByHospital(resources.getHospital()) != null){
            throw new EntityExistException(Rate.class, "operation_quota", resources.getOperation_quota());
        }
        return rateMapper.toDto(rateRepository.save(resources));
    }

    /**
     * 编辑
     * @param resources /
     */
    @Override
    @CacheEvict(allEntries = true)
    @Transactional(rollbackFor = Exception.class)
    public void update(Rate resources) {
        Rate rate = rateRepository.findById(resources.getId()).orElseGet(Rate::new);
        ValidationUtil.isNull(rate.getId(),"Rate","id",resources.getId());

        Rate rate1 = rateRepository.findByHospital(resources.getHospital());

        if(rate1 != null && !rate1.getId().equals(rate.getId())){
            throw new EntityExistException(Rate.class,"Rate",resources.getOperation_quota());
        }

        rate.setOperation_quota(resources.getOperation_quota());
        rate.setDrug_quota(resources.getDrug_quota());
        rate.setHospital(resources.getHospital());
        rate.setPropertion(resources.getPropertion());
        rateRepository.save(rate);
    }

    /**
     * 根据Id查询
     * @param id /
     * @return
     */
    @Override
    @Cacheable(key = "#p0")
    public RateDto findById(long id) {
        Rate Rate = rateRepository.findById(id).orElseGet(Rate::new);
        ValidationUtil.isNull(Rate.getId(),"Rate","id",id);
        return rateMapper.toDto(Rate);
    }

    /**
     * 删除
     * @param ids /
     */
    @Override
    @CacheEvict(allEntries = true)
    @Transactional(rollbackFor = Exception.class)
    public void delete(Set<Long> ids) {
        for (Long id : ids) {
            rateRepository.deleteById(id);
        }
    }

    /**
     * 导出数据
     * @param response /
     * @throws IOException
     */
    @Override
    public void download(List<RateDto> RateDtos, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (RateDto rateDto : RateDtos) {
            Map<String,Object> map = new LinkedHashMap<>();
            map.put("手术报销比例", rateDto.getOperation_quota());
            map.put("药品报销比例", rateDto.getDrug_quota());
            map.put("医院级别", rateDto.getHospital());
            map.put("限额", rateDto.getPropertion());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }

}
